import * as babelParser from '@babel/parser';
import babelGenerator from '@babel/generator';
import type * as t from '@babel/types';
import { transform as babelStandaloneTransform } from '@babel/standalone';

/**
 * Default Babel parser options suitable for modern JS/TS with JSX.
 */
const defaultParserOptions: babelParser.ParserOptions = {
    sourceType: 'module',
    plugins: [
        'typescript', // Enable TypeScript syntax
        'jsx'         // Enable JSX syntax (optional, but often useful)
    ],
    // Add other options if needed, e.g., strictMode: true
};

/**
 * Parses the given code content using Babel parser.
 *
 * @param code The code content (string).
 * @param options Optional Babel parser options to override defaults.
 * @returns The parsed File (AST Root Node).
 * @throws If parsing fails.
 */
export async function parseCode(code: string, options?: babelParser.ParserOptions): Promise<t.File> {
    console.log('[BabelService] Parsing code...');
    try {
        const combinedOptions = { ...defaultParserOptions, ...options };
        const ast = babelParser.parse(code, combinedOptions);
        console.log('[BabelService] Code parsed successfully.');
        return ast;
    } catch (error) {
        console.error('[BabelService] Code parsing failed:', error);
        // Rethrow or handle error appropriately
        throw new Error(`Babel parsing failed: ${error instanceof Error ? error.message : String(error)}`);
    }
}

/**
 * Generates code string from a Babel AST Node.
 *
 * @param node The Babel AST Node (e.g., Expression, Statement, File).
 * @param options Optional Babel generator options.
 * @returns The generated code string.
 * @throws If code generation fails.
 */
export function printAstNode(node: t.Node): string {
    console.log('[BabelService] Printing AST node...');
    try {
        // @ts-ignore - Assuming babelGenerator is default export, adjust if needed
        const output = babelGenerator(node, { /* Options */ });
        console.log('[BabelService] AST node printed successfully.');
        return output.code;
    } catch (error) {
        console.error('[BabelService] AST node printing failed:', error);
        throw new Error(`Babel AST printing failed: ${error instanceof Error ? error.message : String(error)}`);
    }
}

/**
 * Transpiles TypeScript code to JavaScript using @babel/standalone.
 * Handles basic TS syntax and JSX.
 * @param tsCode The TypeScript code string.
 * @returns The transpiled JavaScript code string (synchronous).
 * @throws If transpilation fails.
 */
export function transpileTsToJs(tsCode: string): string {
    console.log('[BabelService] Starting TS to JS transpilation using @babel/standalone...');
    try {
        const result = babelStandaloneTransform(tsCode, {
            presets: [
                'typescript',
                // Configure preset-env to output CommonJS modules
                ['env', { 
                    modules: 'commonjs', // Transpile modules to CommonJS
                    // targets might not be needed when outputting commonjs
                    // targets: { esmodules: true } 
                }]
            ],
            filename: 'temp.ts', 
        });

        if (!result || typeof result.code !== 'string') {
            throw new Error('@babel/standalone transpilation resulted in empty or invalid output.');
        }
        console.log('[BabelService] Standalone transpilation successful. Output length:', result.code.length);
        console.log('[BabelService] Transpiled code (first 200 chars):\n', result.code.substring(0, 200));
        return result.code;
    } catch (error) {
        console.error('[BabelService] @babel/standalone transpilation failed:', error);
        throw new Error(`@babel/standalone transpilation failed: ${error instanceof Error ? error.message : String(error)}`);
    }
}

// Export the service functions
export const babelService = {
    parseCode,
    printAstNode,
    transpileTsToJs,
}; 